using Microsoft.Extensions.Logging;
using SeataNet.Core.Configuration;
using SeataNet.Core.Exceptions;
using SeataNet.Core.Protocol;
using SeataNet.Core.Transaction;
using SeataNet.Core.Common;

namespace SeataNet.Core.RPC
{
    /// <summary>
    /// RPC消息处理器接口
    ///
    /// 定义消息处理的标准接口。实现类负责处理不同类型的RPC消息。
    /// </summary>
    public interface IMessageHandler
    {
        /// <summary>
        /// 异步处理RPC消息
        ///
        /// 接收客户端发来的消息请求，执行相应的业务逻辑，并返回响应消息。
        /// 处理过程应该捕获所有异常以避免导致通道关闭。
        /// </summary>
        /// <param name="request">待处理的请求消息</param>
        /// <returns>处理结果响应消息</returns>
        Task<AbstractMessage> HandleAsync(AbstractMessage request);

        /// <summary>
        /// 获取此处理器支持的消息类型
        /// </summary>
        /// <returns>该处理器可以处理的消息类型</returns>
        MessageType GetSupportedMessageType();
    }

    /// <summary>
    /// 默认RPC消息处理器
    ///
    /// 职责：
    /// 1. 将不同类型的消息分发到对应的处理方法
    /// 2. 调用事务管理器和资源管理器执行事务操作
    /// 3. 构造并返回相应的响应消息
    /// 4. 处理业务逻辑异常
    ///
    /// 支持的消息类型：
    /// - HEARTBEAT_REQUEST: 心跳检测
    /// - GLOBAL_BEGIN: 全局事务开始
    /// - GLOBAL_COMMIT: 全局事务提交
    /// - GLOBAL_ROLLBACK: 全局事务回滚
    /// - BRANCH_REGISTER: 分支事务注册
    /// - BRANCH_REPORT: 分支事务状态上报
    /// - BRANCH_COMMIT: 分支事务提交
    /// - BRANCH_ROLLBACK: 分支事务回滚
    /// </summary>
    public class DefaultMessageHandler : IMessageHandler
    {
        private readonly ILogger<DefaultMessageHandler> _logger;
        private readonly ITransactionManager _transactionManager;
        private readonly IResourceManager _resourceManager;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        /// <param name="transactionManager">事务管理器，处理全局事务操作</param>
        /// <param name="resourceManager">资源管理器，处理分支事务操作</param>
        public DefaultMessageHandler(
            ILogger<DefaultMessageHandler> logger,
            ITransactionManager transactionManager,
            IResourceManager resourceManager)
        {
            _logger = logger;
            _transactionManager = transactionManager;
            _resourceManager = resourceManager;
        }

        public MessageType GetSupportedMessageType()
        {
            return MessageType.HEARTBEAT_REQUEST;
        }

        /// <summary>
        /// 处理RPC消息的主方法
        ///
        /// 流程：
        /// 1. 根据消息类型进行类型转换
        /// 2. 调用对应的专用处理方法
        /// 3. 返回响应消息
        /// 4. 捕获异常并记录日志
        /// </summary>
        /// <param name="request">待处理的消息</param>
        /// <returns>响应消息</returns>
        /// <exception cref="NotSupportedException">消息类型不被支持</exception>
        public async Task<AbstractMessage> HandleAsync(AbstractMessage request)
        {
            try
            {
                _logger.LogDebug($"处理消息: {request.MessageType}");

                return request.MessageType switch
                {
                    // 心跳请求：保活连接
                    MessageType.HEARTBEAT_REQUEST => await HandleHeartbeatRequestAsync((HeartbeatRequest)request),

                    // 全局事务操作
                    MessageType.GLOBAL_BEGIN => await HandleGlobalBeginAsync((GlobalBeginRequest)request),
                    MessageType.GLOBAL_COMMIT => await HandleGlobalCommitAsync((GlobalCommitRequest)request),
                    MessageType.GLOBAL_ROLLBACK => await HandleGlobalRollbackAsync((GlobalRollbackRequest)request),

                    // 分支事务操作
                    MessageType.BRANCH_REGISTER => await HandleBranchRegisterAsync((BranchRegisterRequest)request),
                    MessageType.BRANCH_REPORT => await HandleBranchReportAsync((BranchReportRequest)request),
                    MessageType.BRANCH_COMMIT => await HandleBranchCommitAsync((BranchCommitRequest)request),
                    MessageType.BRANCH_ROLLBACK => await HandleBranchRollbackAsync((BranchRollbackRequest)request),

                    // 未知消息类型
                    _ => throw new NotSupportedException($"不支持的消息类型: {request.MessageType}")
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"处理消息时发生错误: {request.MessageType}");
                throw;
            }
        }

        /// <summary>
        /// 处理心跳请求
        ///
        /// 心跳用于保活连接。客户端定期发送心跳请求给服务器，
        /// 服务器收到后立即返回心跳响应，表示连接正常。
        /// </summary>
        /// <param name="request">心跳请求消息</param>
        /// <returns>心跳响应消息</returns>
        private async Task<AbstractMessage> HandleHeartbeatRequestAsync(HeartbeatRequest request)
        {
            _logger.LogDebug("处理心跳请求");
            return new HeartbeatResponse();
        }

        /// <summary>
        /// 处理全局事务开始请求
        ///
        /// 流程：
        /// 1. 从请求中提取事务名称和超时时间
        /// 2. 调用事务管理器生成XID（全局事务ID）
        /// 3. 将XID和事务状态返回给客户端
        ///
        /// 该方法返回的XID将成为全局事务的唯一标识，后续所有分支操作都要关联此XID。
        /// </summary>
        /// <param name="request">全局事务开始请求</param>
        /// <returns>全局事务开始响应，包含XID和事务状态</returns>
        private async Task<AbstractMessage> HandleGlobalBeginAsync(GlobalBeginRequest request)
        {
            _logger.LogDebug($"处理全局事务开始请求: {request.TransactionName}");

            var xid = await _transactionManager.BeginAsync(
                request.Timeout,
                request.TransactionName);

            return new GlobalBeginResponse
            {
                Xid = xid,
                TransactionStatus = TransactionStatus.Begin
            };
        }

        /// <summary>
        /// 处理全局事务提交请求
        ///
        /// 流程：
        /// 1. 根据XID查询该全局事务的所有分支
        /// 2. 对每个分支执行提交操作
        /// 3. 返回提交结果
        ///
        /// 只有当所有分支都提交成功时，全局事务才算提交成功。
        /// </summary>
        /// <param name="request">全局事务提交请求，包含XID</param>
        /// <returns>全局事务提交响应，包含最终结果</returns>
        private async Task<AbstractMessage> HandleGlobalCommitAsync(GlobalCommitRequest request)
        {
            _logger.LogDebug($"处理全局事务提交请求: {request.Xid}");

            var success = await _transactionManager.CommitAsync(request.Xid);

            return new GlobalCommitResponse
            {
                Xid = request.Xid,
                TransactionId = request.TransactionId,
                TransactionStatus = success ? TransactionStatus.Committed : TransactionStatus.Failed
            };
        }

        /// <summary>
        /// 处理全局事务回滚请求
        ///
        /// 流程：
        /// 1. 根据XID查询该全局事务的所有分支
        /// 2. 对每个分支执行回滚操作（逆序执行）
        /// 3. 返回回滚结果
        ///
        /// 回滚会撤销分支已执行的DML操作，恢复到事务开始前的状态。
        /// </summary>
        /// <param name="request">全局事务回滚请求，包含XID</param>
        /// <returns>全局事务回滚响应，包含最终结果</returns>
        private async Task<AbstractMessage> HandleGlobalRollbackAsync(GlobalRollbackRequest request)
        {
            _logger.LogDebug($"处理全局事务回滚请求: {request.Xid}");

            var success = await _transactionManager.RollbackAsync(request.Xid);

            return new GlobalRollbackResponse
            {
                Xid = request.Xid,
                TransactionId = request.TransactionId,
                TransactionStatus = success ? TransactionStatus.RolledBack : TransactionStatus.Failed
            };
        }

        /// <summary>
        /// 处理分支事务注册请求
        ///
        /// 流程：
        /// 1. 记录分支的基本信息（XID、资源ID、锁键等）
        /// 2. 分配分支ID
        /// 3. 在事务协调器中注册该分支
        /// 4. 返回分支ID给客户端
        ///
        /// 分支注册后，该分支在全局事务中才能执行后续操作（DML、提交、回滚等）。
        /// </summary>
        /// <param name="request">分支注册请求，包含XID、资源ID等</param>
        /// <returns>分支注册响应，包含分配的分支ID</returns>
        private async Task<AbstractMessage> HandleBranchRegisterAsync(BranchRegisterRequest request)
        {
            _logger.LogDebug($"处理分支事务注册请求: {request.Xid}, 资源ID: {request.ResourceId}");

            var branchId = await _resourceManager.BranchRegisterAsync(
                request.BranchType.ToString(),
                request.Xid,
                request.ResourceId,
                request.LockKey);

            return new BranchRegisterResponse
            {
                BranchId = branchId,
                ResultCode = ResultCode.Success,
                TransactionStatus = TransactionStatus.Begin
            };
        }

        /// <summary>
        /// 处理分支事务状态报告请求
        ///
        /// 分支在执行本地事务后，需要向协调器报告执行结果（成功或失败）。
        /// 协调器根据所有分支的报告结果决定是否执行全局提交或回滚。
        ///
        /// 流程：
        /// 1. 接收分支的执行状态
        /// 2. 更新该分支在协调器中的状态
        /// 3. 根据所有分支的状态决定下一步操作
        /// </summary>
        /// <param name="request">分支报告请求，包含XID、分支ID、状态等</param>
        /// <returns>分支报告响应，包含处理结果</returns>
        private async Task<AbstractMessage> HandleBranchReportAsync(BranchReportRequest request)
        {
            _logger.LogDebug($"处理分支事务报告请求: {request.Xid}, 分支ID: {request.BranchId}");

            var success = await _resourceManager.BranchReportAsync(
                request.Xid,
                request.BranchId,
                (int)request.BranchStatus,
                request.ApplicationData);

            return new BranchReportResponse
            {
                TransactionStatus = success ? TransactionStatus.Committed : TransactionStatus.Failed
            };
        }

        /// <summary>
        /// 处理分支事务提交请求
        ///
        /// 在提交阶段，协调器要求分支提交本地事务。
        /// 分支需要：
        /// 1. 提交本地DML事务
        /// 2. 删除undo_log日志记录
        /// 3. 释放本地锁
        ///
        /// 此时分支的修改已经在本地数据库中持久化。
        /// </summary>
        /// <param name="request">分支提交请求，包含XID、分支ID等</param>
        /// <returns>分支提交响应，包含提交结果</returns>
        private async Task<AbstractMessage> HandleBranchCommitAsync(BranchCommitRequest request)
        {
            _logger.LogDebug($"处理分支事务提交请求: {request.Xid}, 分支ID: {request.BranchId}");

            var success = await _resourceManager.BranchCommitAsync(
                request.BranchType.ToString(),
                request.Xid,
                request.BranchId,
                request.ResourceId,
                request.ApplicationData);

            return new BranchCommitResponse
            {
                BranchStatus = success ? BranchStatus.PhaseTwoCommitted : BranchStatus.Failed
            };
        }

        /// <summary>
        /// 处理分支事务回滚请求
        ///
        /// 在回滚阶段，协调器要求分支回滚本地事务。
        /// 分支需要：
        /// 1. 查询undo_log日志
        /// 2. 根据日志反向生成回滚SQL
        /// 3. 执行回滚SQL以恢复数据
        /// 4. 删除undo_log日志记录
        /// 5. 释放本地锁
        ///
        /// 此过程确保分支的修改被完全撤销。
        /// </summary>
        /// <param name="request">分支回滚请求，包含XID、分支ID等</param>
        /// <returns>分支回滚响应，包含回滚结果</returns>
        private async Task<AbstractMessage> HandleBranchRollbackAsync(BranchRollbackRequest request)
        {
            _logger.LogDebug($"处理分支事务回滚请求: {request.Xid}, 分支ID: {request.BranchId}");

            var success = await _resourceManager.BranchRollbackAsync(
                request.BranchType.ToString(),
                request.Xid,
                request.BranchId,
                request.ResourceId,
                request.ApplicationData);

            return new BranchRollbackResponse
            {
                BranchStatus = success ? BranchStatus.PhaseTwoRollbacked : BranchStatus.Failed
            };
        }
    }

    /// <summary>
    /// RPC消息序列化器接口
    ///
    /// 定义消息序列化/反序列化的标准接口。
    /// 支持不同的序列化格式（二进制、JSON等）。
    /// </summary>
    public interface IMessageSerializer
    {
        /// <summary>
        /// 将消息序列化为字节数组
        /// </summary>
        /// <param name="message">待序列化的消息</param>
        /// <returns>序列化后的字节数组</returns>
        byte[] Serialize(AbstractMessage message);

        /// <summary>
        /// 将字节数组反序列化为消息对象
        /// </summary>
        /// <param name="data">待反序列化的字节数组</param>
        /// <returns>反序列化后的消息对象</returns>
        AbstractMessage Deserialize(byte[] data);
    }

    /// <summary>
    /// 二进制消息序列化器
    ///
    /// 使用Seata框架的二进制格式序列化消息。
    /// 相比JSON，二进制格式更加紧凑，传输效率更高。
    ///
    /// 优点：
    /// - 消息体更小，网络传输更快
    /// - 解析效率高
    /// - 兼容Seata标准协议
    /// </summary>
    public class BinaryMessageSerializer : IMessageSerializer
    {
        private readonly ILogger<BinaryMessageSerializer> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        public BinaryMessageSerializer(ILogger<BinaryMessageSerializer> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 序列化消息
        ///
        /// 调用消息对象的Encode()方法进行序列化。
        /// 每个消息类都应该实现Encode()方法以返回二进制表示。
        /// </summary>
        /// <param name="message">待序列化的消息</param>
        /// <returns>二进制消息数据</returns>
        public byte[] Serialize(AbstractMessage message)
        {
            try
            {
                return message.Encode();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"序列化消息时发生错误: {message.MessageType}");
                throw;
            }
        }

        /// <summary>
        /// 反序列化消息
        ///
        /// 使用消息工厂根据二进制数据重构消息对象。
        /// 二进制数据的格式遵循Seata协议规范。
        /// </summary>
        /// <param name="data">二进制消息数据</param>
        /// <returns>反序列化后的消息对象</returns>
        public AbstractMessage Deserialize(byte[] data)
        {
            try
            {
                return MessageFactory.DecodeMessage(data);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "反序列化消息时发生错误");
                throw;
            }
        }
    }

    /// <summary>
    /// RPC消息传输器接口
    ///
    /// 定义消息网络传输的标准接口。
    /// 负责将序列化后的消息通过网络发送和接收。
    /// </summary>
    public interface IMessageTransporter
    {
        /// <summary>
        /// 发送消息并等待响应（使用默认超时）
        /// </summary>
        /// <param name="request">待发送的消息</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>响应消息</returns>
        Task<AbstractMessage> SendAsync(AbstractMessage request, CancellationToken cancellationToken = default);

        /// <summary>
        /// 发送单向消息（不等待响应）
        /// </summary>
        /// <param name="request">待发送的消息</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>发送完成</returns>
        Task SendOnewayAsync(AbstractMessage request, CancellationToken cancellationToken = default);

        /// <summary>
        /// 发送消息并等待响应（指定超时）
        /// </summary>
        /// <param name="request">待发送的消息</param>
        /// <param name="timeout">超时时间</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>响应消息</returns>
        Task<AbstractMessage> SendAsync(AbstractMessage request, TimeSpan timeout, CancellationToken cancellationToken = default);
    }

    /// <summary>
    /// HTTP消息传输器
    ///
    /// 职责：
    /// 1. 使用HTTP协议传输Seata消息
    /// 2. 支持请求/响应模式和单向消息模式
    /// 3. 处理超时和异常
    /// 4. 负责消息的序列化和反序列化
    ///
    /// 工作流程：
    /// 1. 使用IMessageSerializer将消息序列化为字节数组
    /// 2. 通过HTTP POST请求发送到指定地址
    /// 3. 对于双向消息，等待并读取HTTP响应
    /// 4. 反序列化响应数据并返回消息对象
    /// </summary>
    public class HttpMessageTransporter : IMessageTransporter
    {
        private readonly HttpClient _httpClient;
        private readonly IMessageSerializer _serializer;
        private readonly SeataConfiguration _configuration;
        private readonly ILogger<HttpMessageTransporter> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="httpClient">HTTP客户端</param>
        /// <param name="serializer">消息序列化器</param>
        /// <param name="configuration">Seata配置</param>
        /// <param name="logger">日志记录器</param>
        public HttpMessageTransporter(
            HttpClient httpClient,
            IMessageSerializer serializer,
            SeataConfiguration configuration,
            ILogger<HttpMessageTransporter> logger)
        {
            _httpClient = httpClient;
            _serializer = serializer;
            _configuration = configuration;
            _logger = logger;
        }

        /// <summary>
        /// 发送消息并等待响应（使用配置中的默认超时）
        /// </summary>
        /// <param name="request">待发送的消息</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>响应消息</returns>
        public async Task<AbstractMessage> SendAsync(AbstractMessage request, CancellationToken cancellationToken = default)
        {
            return await SendAsync(request, _configuration.Transport.Timeout, cancellationToken);
        }

        /// <summary>
        /// 发送单向消息
        ///
        /// 流程：
        /// 1. 序列化消息
        /// 2. 发送HTTP POST请求
        /// 3. 不等待或忽略响应
        /// 4. 若发送失败仅记录警告日志
        /// </summary>
        /// <param name="request">待发送的消息</param>
        /// <param name="cancellationToken">取消令牌</param>
        public async Task SendOnewayAsync(AbstractMessage request, CancellationToken cancellationToken = default)
        {
            try
            {
                var content = new ByteArrayContent(_serializer.Serialize(request));
                var response = await _httpClient.PostAsync($"{_configuration.Transport.ServerAddress}/seata/message", content, cancellationToken);

                if (!response.IsSuccessStatusCode)
                {
                    _logger.LogWarning($"单向发送消息失败: {response.StatusCode}");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"单向发送消息时发生错误: {request.MessageType}");
                throw;
            }
        }

        /// <summary>
        /// 发送消息并等待响应（指定超时）
        ///
        /// 流程：
        /// 1. 序列化请求消息
        /// 2. 创建带超时的CancellationToken
        /// 3. 通过HTTP POST发送消息
        /// 4. 等待并读取HTTP响应
        /// 5. 反序列化响应消息
        /// 6. 捕获超时异常并转换为RpcException
        /// </summary>
        /// <param name="request">待发送的消息</param>
        /// <param name="timeout">超时时间</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>响应消息</returns>
        /// <exception cref="RpcException">消息发送失败或超时</exception>
        public async Task<AbstractMessage> SendAsync(AbstractMessage request, TimeSpan timeout, CancellationToken cancellationToken = default)
        {
            try
            {
                // 创建链接的CancellationTokenSource，支持外部取消和超时自动取消
                using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                cts.CancelAfter(timeout);

                // 序列化请求消息
                var content = new ByteArrayContent(_serializer.Serialize(request));

                // 发送HTTP POST请求
                var response = await _httpClient.PostAsync($"{_configuration.Transport.ServerAddress}/seata/message", content, cts.Token);

                // 检查HTTP响应状态
                if (!response.IsSuccessStatusCode)
                {
                    throw new RpcException($"发送消息失败: {response.StatusCode}");
                }

                // 读取响应数据并反序列化
                var responseData = await response.Content.ReadAsByteArrayAsync(cts.Token);
                return _serializer.Deserialize(responseData);
            }
            catch (OperationCanceledException ex) when (ex.InnerException is TimeoutException)
            {
                _logger.LogError(ex, $"发送消息超时: {request.MessageType}");
                throw new RpcException($"发送消息超时: {request.MessageType}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"发送消息时发生错误: {request.MessageType}");
                throw;
            }
        }
    }

    /// <summary>
    /// RPC消息处理器注册表接口
    ///
    /// 管理所有消息处理器的注册和查询。
    /// 支持动态注册/注销处理器。
    /// </summary>
    public interface IMessageHandlerRegistry
    {
        /// <summary>
        /// 注册消息处理器
        /// </summary>
        /// <param name="handler">待注册的处理器</param>
        void RegisterHandler(IMessageHandler handler);

        /// <summary>
        /// 注销指定消息类型的处理器
        /// </summary>
        /// <param name="messageType">消息类型</param>
        void UnregisterHandler(MessageType messageType);

        /// <summary>
        /// 获取指定消息类型的处理器
        /// </summary>
        /// <param name="messageType">消息类型</param>
        /// <returns>对应的处理器，如果未找到则返回null</returns>
        IMessageHandler GetHandler(MessageType messageType);

        /// <summary>
        /// 获取所有已注册的处理器
        /// </summary>
        /// <returns>处理器集合</returns>
        IEnumerable<IMessageHandler> GetAllHandlers();
    }

    /// <summary>
    /// 默认RPC消息处理器注册表
    ///
    /// 职责：
    /// 1. 维护消息类型到处理器的映射关系
    /// 2. 支持处理器的注册和注销
    /// 3. 根据消息类型快速查找对应的处理器
    /// 4. 线程安全：使用字典实现，支持并发读取
    ///
    /// 实现细节：
    /// - 使用Dictionary<MessageType, IMessageHandler>存储映射关系
    /// - 每个消息类型只能对应一个处理器
    /// - 注册新处理器会覆盖旧的处理器
    /// </summary>
    public class DefaultMessageHandlerRegistry : IMessageHandlerRegistry
    {
        private readonly Dictionary<MessageType, IMessageHandler> _handlers = new();
        private readonly ILogger<DefaultMessageHandlerRegistry> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        public DefaultMessageHandlerRegistry(ILogger<DefaultMessageHandlerRegistry> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 注册消息处理器
        ///
        /// 流程：
        /// 1. 调用处理器的GetSupportedMessageType()获取其支持的消息类型
        /// 2. 将处理器存储到字典中，相同消息类型的处理器会被覆盖
        /// 3. 记录注册日志
        /// </summary>
        /// <param name="handler">待注册的处理器</param>
        public void RegisterHandler(IMessageHandler handler)
        {
            var messageType = handler.GetSupportedMessageType();
            _handlers[messageType] = handler;
            _logger.LogDebug($"注册消息处理器: {messageType}");
        }

        /// <summary>
        /// 注销消息处理器
        ///
        /// 移除指定消息类型对应的处理器。
        /// 如果该消息类型未注册任何处理器，操作无效。
        /// </summary>
        /// <param name="messageType">待注销的消息类型</param>
        public void UnregisterHandler(MessageType messageType)
        {
            if (_handlers.Remove(messageType))
            {
                _logger.LogDebug($"注销消息处理器: {messageType}");
            }
        }

        /// <summary>
        /// 获取消息处理器
        ///
        /// 根据消息类型查找对应的处理器。
        /// 如果未找到，返回null。
        /// </summary>
        /// <param name="messageType">消息类型</param>
        /// <returns>对应的处理器或null</returns>
        public IMessageHandler GetHandler(MessageType messageType)
        {
            _handlers.TryGetValue(messageType, out var handler);
            return handler;
        }

        /// <summary>
        /// 获取所有处理器
        ///
        /// 返回所有已注册的处理器集合。
        /// </summary>
        /// <returns>处理器集合</returns>
        public IEnumerable<IMessageHandler> GetAllHandlers()
        {
            return _handlers.Values;
        }
    }
}
